package io.renren.modules.generator.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.renren.common.enums.FileStatus;
import io.renren.common.exception.RRException;
import io.renren.common.utils.ShiroUtils;
import io.renren.modules.generator.constant.UrlConstant;
import io.renren.modules.generator.entity.FileEntity;
import io.renren.modules.generator.service.FileService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;

import io.renren.modules.generator.dao.MkdirDao;
import io.renren.modules.generator.entity.MkdirEntity;
import io.renren.modules.generator.service.MkdirService;


@Service("mkdirService")
public class MkdirServiceImpl extends ServiceImpl<MkdirDao, MkdirEntity> implements MkdirService {

    @Autowired
    private FileService fileService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete", FileStatus.NORMAL.getStatus());
        wrapper.eq("user_id", ShiroUtils.getUserId());
        if (StringUtils.isNotBlank((String) params.get("name"))) {
            wrapper.like("dir_name", params.get("name"));
        }
        IPage<MkdirEntity> page = this.page(
                new Query<MkdirEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void saveDir(MkdirEntity mkdir) {
        String relativeUrl = "";
        String dirName = mkdir.getDirName();
        if (Objects.nonNull(mkdir.getLastDirId())) {
            MkdirEntity entity = baseMapper.selectById(mkdir.getLastDirId());
            relativeUrl = relativeUrl + entity.getRelativeUrl() + "/";
        }
        //在文件服务器上创建文件夹的地址
        String dirUrl = UrlConstant.dirUrl + relativeUrl + dirName;
        //文件服务器访问地址
        String fileUrl = UrlConstant.fileUrl + relativeUrl + dirName;
        File file = new File(dirUrl);
        if (file.exists()) {
            throw new RRException("文件夹已存在,请重新创建");
        } else {
            file.mkdirs();
        }

        mkdir.setLocalDir(dirUrl);

        mkdir.setDirUrl(fileUrl);
        //默认设置文件夹为未删除
        mkdir.setIsDelete(FileStatus.NORMAL.getStatus());
        //设置相对文件夹路径
        mkdir.setRelativeUrl(relativeUrl + dirName);
        //设置文件夹创建时间
        mkdir.setCreateTime(new Date());
        //设置文件夹创建用户
        mkdir.setUserId(ShiroUtils.getUserId());

        baseMapper.insert(mkdir);

    }

    @Override
    public void updateDir(MkdirEntity mkdir) {
        String relativeUrl = "";

        //获取文件的本地目录
        String localDir = UrlConstant.dirUrl + relativeUrl;
        //获取文件夹在文件服务器的访问上级目录
        String dirUrl = UrlConstant.fileUrl + relativeUrl;

        if (Objects.nonNull(mkdir.getLastDirId())) {
            MkdirEntity entity = baseMapper.selectById(mkdir.getLastDirId());
            relativeUrl = relativeUrl + entity.getRelativeUrl();
            mkdir.setRelativeUrl(relativeUrl + "/" + mkdir.getDirName());
        } else {
            dirUrl = dirUrl.substring(0, dirUrl.length()-1);
        }

        String localDirPath = localDir + "/" + mkdir.getDirName();
        String httpUrl = dirUrl + "/" + mkdir.getDirName();
        //新建新文件夹
        File file = new File(localDirPath);
        file.mkdirs();

        mkdir.setLocalDir(localDirPath);
        mkdir.setDirUrl(httpUrl);

        baseMapper.updateById(mkdir);


    }

    @Override
    public void deleteDir(Integer dirId) {
        MkdirEntity mkdirEntity = baseMapper.selectById(dirId);
        QueryWrapper<FileEntity> wrapper = new QueryWrapper<>();
        wrapper.select("file_id").eq("dir_id", dirId);
        //删除文件夹中文件在库中的信息
        fileService.list(wrapper).forEach(file -> {
            fileService.removeById(file.getFileId());
        });
        String localDir = mkdirEntity.getLocalDir();
        File file = new File(localDir);
        deleteDir(file);
        baseMapper.deleteById(dirId);


    }

    @Override
    public List<MkdirEntity> selectAll() {
        QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
        wrapper.select("dir_id", "dir_name");
        //未被删除文件夹
        wrapper.eq("is_delete", FileStatus.NORMAL.getStatus());
        //所属用户文件夹
        wrapper.eq("user_id", ShiroUtils.getUserId());

        return baseMapper.selectList(wrapper);
    }

    @Override
    public void reclaim(Integer dirId) {
        try {
            baseMapper.reclaim(dirId);
            QueryWrapper<FileEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("dir_id", dirId).eq("is_delete", FileStatus.DELETE.getStatus());
            List<FileEntity> list = fileService.list(wrapper);
            if (list.size() > 0) {
                list.forEach(fileEntity -> {
                    UpdateWrapper<FileEntity> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("file_id", fileEntity.getFileId());
                    updateWrapper.set("is_delete", FileStatus.NORMAL.getStatus());
                    fileService.update(updateWrapper);
                });
            }
        } catch (Exception e) {
            throw new RRException("文件回收失败-状态时间改变失败");
        }

    }

    @Override
    public PageUtils queryDeletePage(Map<String, Object> params) {
        QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete", FileStatus.DELETE.getStatus());
        if (StringUtils.isNotBlank(params.get("name").toString())) {
            wrapper.like("dir_name", params.get("name"));
        }
        IPage<MkdirEntity> page = this.page(
                new Query<MkdirEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public List<MkdirEntity> getUpDir(Integer dirId) {
        QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
        wrapper.select("dir_id", "dir_name");
        //未被删除文件夹
        wrapper.eq("is_delete", FileStatus.NORMAL.getStatus());

        List<MkdirEntity> list = baseMapper.selectList(wrapper);

        //删除自己的文件夹信息
        list.removeIf(mkdirEntity -> mkdirEntity.getDirId().equals(dirId));

        return list;
    }

    @Override
    public void clearAll() {
        Long userId = ShiroUtils.getUserId();
        try {
            QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
            wrapper.select("dir_id").eq("is_delete", FileStatus.DELETE.getStatus());
            wrapper.eq("user_id", userId);
            List<MkdirEntity> mkdirEntities = baseMapper.selectList(wrapper);
            if (mkdirEntities.size() > 0) {
                for (MkdirEntity mkdirEntity : mkdirEntities) {
                    deleteDir(mkdirEntity.getDirId());
                    QueryWrapper<FileEntity> fileWrapper = new QueryWrapper<>();
                    fileWrapper.select("file_id", "file_url");
                    fileWrapper.eq("dir_id", mkdirEntity.getDirId());
                    fileWrapper.eq("user_id", userId);
                    List<FileEntity> list = fileService.list(fileWrapper);
                    if (list.size() > 0) {
                        list.forEach(file -> {
                            deleteFile(file);
                        });

                    }

                }
            }
            QueryWrapper<FileEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("file_id", "file_url").eq("is_delete", FileStatus.DELETE.getStatus());
            queryWrapper.eq("user_id", userId);
            List<FileEntity> list = fileService.list(queryWrapper);
            list.forEach(file -> {
                deleteFile(file);
            });
        } catch (Exception e) {
            throw new RRException("文件回收失败");
        }

    }

    @Override
    public List<FileEntity> getDirFile(Integer dirId) {
        QueryWrapper<FileEntity> wrapper = new QueryWrapper<>();
        wrapper.select("file_id", "file_name", "create_time");
        wrapper.eq("dir_id", dirId);
        return fileService.list(wrapper);
    }

    @Override
    public void autoClear() {
        Long userId = ShiroUtils.getUserId();
        try {
            Date date = new Date();
            QueryWrapper<MkdirEntity> wrapper = new QueryWrapper<>();
            wrapper.select("dir_id");
            wrapper.eq("user_id", userId).eq("is_delete", FileStatus.DELETE.getStatus());
            wrapper.lt("delete_time", date);
            List<MkdirEntity> mkdirEntities = baseMapper.selectList(wrapper);
            if (mkdirEntities.size() > 0) {
                for (MkdirEntity mkdirEntity : mkdirEntities) {
                    QueryWrapper<FileEntity> fileWrapper = new QueryWrapper<>();
                    fileWrapper.select("file_id", "file_url");
                    fileWrapper.eq("dir_id", mkdirEntity.getDirId()).eq("user_id", userId);
                    List<FileEntity> list = fileService.list(fileWrapper);
                    if (list.size() > 0) {
                        list.forEach(file -> {
                            deleteFile(file);
                        });
                    }
                    deleteDir(mkdirEntity.getDirId());
                }
            }
            QueryWrapper<FileEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("file_id", "file_url").eq("is_delete", FileStatus.DELETE.getStatus());
            queryWrapper.eq("user_id", userId);
            queryWrapper.lt("delete_time", date);
            List<FileEntity> list = fileService.list(queryWrapper);
            if (list.size() > 0) {
                list.forEach(file -> {
                    deleteFile(file);
                });
            }
        } catch (Exception e) {
            log.error("文件自动回收失败", e);
            throw new RRException("文件到期回收失败");
        }


    }

    private void deleteFile(FileEntity file) {
        Integer fileId = file.getFileId();
        String url = UrlConstant.dirUrl + file.getFileUrl().substring(22);
        File oldFile = new File(url);
        oldFile.delete();
        fileService.removeById(fileId);
    }

    private static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }


}
